﻿using System;
using System.Collections.Generic;
using DrawableObjects.Actors;
using SpecialEffects;
using DrawableObjects.Actors.Aircrafts;
using DrawableObjects.Actors.Projectiles;
using LightEffects;

namespace WorldView
{
    public class GenericDrawableList
    {
        private Type[] basicActorTypes = new Type[]{typeof(Aircraft), typeof(Item), typeof(Projectile)};

        private List<List<Actor>> actorList;

        private List<SpecialEffect> specialEffectList;
        

        /// <summary>
        /// searches for the actors with the Type T and the Owner owner.
        /// Writes them in a list and returns it.
        /// </summary>
        public List<Actor> getActors(Type T, Owner owner)
        {
            List<Actor> returnList = new List<Actor>();
            int i = 0;
            bool found = false;
            while (i < actorList.Count && !found)
            {
                if (actorList[i].Count > 0)
                {
                    if (actorList[i][0].owner == owner && (actorList[i][0].GetType().IsSubclassOf(T) || actorList[i][0].GetType() == T))
                    {
                        returnList = actorList[i];
                        found = true;
                    }
                }
                i++;
            }
            return returnList;
        }

        /// <summary>
        /// searches the actors with the Type T and returns them in a List.
        /// </summary>
        public List<Actor> getActors(Type T)
        {
            List<Actor> returnList = new List<Actor>();
            int i = 0;
            while (i < actorList.Count)
            {
                if (actorList[i].Count > 0)
                {
                    if (actorList[i][0].GetType().IsSubclassOf(T) || actorList[i][0].GetType() == T)
                    {
                        returnList.InsertRange(returnList.Count, actorList[i]);
                    }
                }
                i++;
            }
            return returnList;
        }

        public List<Actor> getActors()
        {
            List<Actor> completeList = new List<Actor>();
            foreach (List<Actor> list in actorList)
            {
                completeList.InsertRange(completeList.Count, list);
            }
            return completeList;
        }
        /// <summary>
        /// adds the actor
        /// </summary>
        /// <param name="actor"></param>
        public void addActor(Actor actor)
        {
            Owner owner = actor.owner;
            Type T = null;
            int i = 0;
            while (T == null && i < basicActorTypes.Length)
            {
                if (basicActorTypes[i].IsAssignableFrom(actor.GetType()))
                {
                    List<Actor> typeList = null;
                    T = basicActorTypes[i];
                    int j = 0;
                    while (j < actorList.Count && typeList == null) 
                    {
                        if (actorList[j].Count > 0)
                        {
                            if (actorList[j][0].owner == owner && T.IsAssignableFrom(actorList[j][0].GetType()))
                            {
                                typeList = actorList[j];
                            }
                        }
                        j++;
                    }
                    if (typeList == null)
                    {
                        List<Actor> newList = new List<Actor>();
                        newList.Add(actor);
                        actorList.Add(newList);
                    }
                    else
                    {
                        typeList.Add(actor);
                    }
                }
                i++;
            }
        }
        /// <summary>
        /// removes the actor
        /// </summary>
        /// <param name="actor"></param>
        public virtual void removeActor(Actor actor)
        {
            Type T = getBasicActorType(actor);
            List<Actor> removeList = getActors(T, actor.owner);
            if (removeList != null)
            {
                if (removeList.Contains(actor))
                {
                    removeList.Remove(actor);
                }
                if (removeList.Count == 0)
                {
                    actorList.Remove(removeList);
                }
            }
        }

        /// <summary>
        /// Tries to match the actor to one of the basic types in actorTypes. Returns null if no type is a match
        /// </summary>
        private Type getBasicActorType(Actor actor)
        {
            Type T = null;
            int i = 0;
            while (T == null && i < basicActorTypes.Length)
            {
                if (actor.GetType().IsSubclassOf(basicActorTypes[i]))
                {
                    T = basicActorTypes[i];
                }
                i++;
            }
            return T;
        }

        public void addSpecialEffect(SpecialEffect specialEffect)
        {
            specialEffectList.Add(specialEffect);
        }

        public List<SpecialEffect> getSpecialEffects(Type T)
        {
            List<SpecialEffect> specialEffects = new List<SpecialEffect>();
            foreach (SpecialEffect effect in specialEffectList)
            {
                if (T.IsSubclassOf(effect.GetType()) || T == effect.GetType())
                {
                    specialEffects.Add(effect);
                }
            }
            return specialEffects; 
        }

        public List<SpecialEffect> getSpecialEffects()
        {
            return specialEffectList;
        }

        public void removeSpecialEffect(SpecialEffect specialEffect)
        {
            specialEffectList.Remove(specialEffect);
        }

        public GenericDrawableList()
        {
            actorList = new List<List<Actor>>();
            specialEffectList = new List<SpecialEffect>();
        } 
    }
}

